#include "config.h"

#include <float.h>
#include <sdr.h>
#include "rt.h"
#include "opt.h"

/* TODO */
static double fov = QUARTER_PI;

ray_t primary_ray(int x, int y, int sample)
{
	ray_t res;
	double aspect = (double)opt.width / (double)opt.height;

	double ysz = 2.0;
	double xsz = aspect * ysz;

	double px = ((double)x / (double)opt.width) * xsz - xsz / 2.0;
	double py = 1.0 - ((double)y / (double)opt.height) * ysz;

	res.origin = v3_cons(0, 0, 0);
	res.dir.x = px * 100.0;
	res.dir.y = py * 100.0;
	res.dir.z = 1.0 / tan(0.5 * fov) * 100.0;

	return res;
}

struct object *ray_test(struct scene *scn, ray_t ray, struct isect_point *isect_pt)
{
	int i, nobj = scn_object_count(scn);
	struct object *nearest = 0;
	struct isect_point nearest_isect;

	nearest_isect.dist = DBL_MAX;

	for(i=0; i<nobj; i++) {
		struct isect_point pt;
		struct object *obj = scn_object(scn, i);

		if(obj_intersect(obj, ray, &pt) && pt.dist < nearest_isect.dist) {
			nearest_isect = pt;
			nearest = obj;
		}
	}

	if(isect_pt) {
		*isect_pt = nearest_isect;
	}
	return nearest;
}

void trace(struct scene *scn, ray_t ray, struct subpixel *res)
{
	struct object *obj;
	struct isect_point pt;

	res->r = 0.1;
	res->g = 0.1;
	res->b = 0.1;

	if((obj = ray_test(scn, ray, &pt))) {
		struct material *mat = obj_get_material(obj);
		struct shader *sdr = mat_get_shader(mat);

		if(sdr) {
			vec4_t col = sdr_shade(sdr, ray, &pt, mat, scn);
			res->r = col.x;
			res->g = col.y;
			res->b = col.z;
		} else {
			res->r = res->g = res->b = 1.0;
		}
	}
}
